package model;

import java.sql.SQLException;
import java.util.LinkedList;

import database.*;

import model.trivial_pursuit.DbTPInstaller;

/**
 * Classe permettant de créer les tables dans la base de données principale
 * @author Aubry Pirian
 * version 1.0
 */
public class DbInstaller {
	
	private IDbConnector idbc;		// Objet de connexion
	
	private String[] tableName;
	
	/**
	 * Constructeur de la classe
	 * Crée automatiquement les tables
	 */
	public DbInstaller () {
		this.install();
	}
	
	/**
	 * Constructeur de la classe
	 * Crée automatiquement les tables, en vidant au préalable si force==true
	 * @param force : true s'il faut d'abord vider la base de données, false sinon
	 */
	public DbInstaller (boolean force) {
		this.install(force);
	}
	
	/**
	 * Lance l'installation sans effacer les tables déjà présentes
	 */
	private void install() {
		this.install(false);
	}
	
	/**
	 * Lance l'installation en effaçant éventuellement les tables déjà présentes
	 * @param force : true s'il faut d'abord vider la base de données, false sinon
	 */
	private void install(boolean force) {
		try {
			this.idbc = new MySQLConnector(Params.DB_SERVER,Params.DB_USER,Params.DB_PASSWD,Params.DB_NAME);
		} catch (NoSuchFieldException e) {
			System.err.println("Paramètres de connexion non valides.");
		}
		try {
			this.idbc.connect();
		} catch (SQLException e) {
			System.err.println("Echec de la connexion à la base de données : SQL n°"+e.getErrorCode());
		} catch (ClassNotFoundException e) {
			System.err.println("Echec de la connexion à la base de données (class not found).");
		}
		this.init();
		int tCount = tableName.length;
		if (force) {
			for (int t=0; t<tCount; t++) {
				try {
					this.idbc.dropTable(tableName[t]);
				} catch (SQLException e) {
					System.err.println("Impossible de supprimer la table "+tableName[t]+" : SQL n°"+e.getErrorCode());
				} catch (NoSuchFieldException e) {
					System.err.println("Impossible de supprimer la table "+tableName[t]+" > Paramètre non valide");
				}
			}
		}
		for (int t=0; t<tCount; t++) {
			try {
				this.createTable(t);
			} catch (SQLException e) {
				System.err.println("Impossible de créer la table "+tableName[t]+" : SQL n°"+e.getErrorCode());
			} catch (NoSuchFieldException e) {
				System.err.println("Impossible de créer la table "+tableName[t]+" : paramètre non valide");
			}
		}
	}
	
	/**
	 * Initialise les noms des tables pour le tableau tableName
	 */
	public void init () {
		// Table names
		tableName = new String[5];
		tableName[Params.MEMBER_ID] = "member";
		tableName[Params.ROOM_ID] = "room";
		tableName[Params.GAME_ID] = "game";
		tableName[Params.MATCH_ID] = "match";
		tableName[Params.CONNECTION_ID] = "connection";
	}
	
	/**
	 * Crée la table numéro 'table'
	 * @param tableId		: numéro de la table à créer
	 * @throws NoSuchFieldException : paramètre non valide
	 * @throws SQLException 
	 */
	private void createTable (int tableId) throws NoSuchFieldException, SQLException {
		String tName = tableName[tableId];
		LinkedList<TypedAttribute> attributes = new LinkedList<TypedAttribute>();
		int aCount = Params.TABLE_ATTRIBUTES[tableId].length;
		for (int a=0; a<aCount; a++) {
			this.appendAttribute(attributes,Params.TABLE_ATTRIBUTES[tableId][a]);
		}
		try {
			this.idbc.createTable(tName, attributes);
		} catch (NoSuchFieldException e) {
			throw e;
		} catch (SQLException e) {
			throw e;
		}
	}
	
	/**
	 * Ajoute à la liste l'attribut du tableau Params.TABLE_ATTRIBUTES
	 * @param list	: liste d'Attributes
	 * @param table : index de la table dans le tableau
	 * @param att	: index de l'attribut dans le tableau
	 */
	private void appendAttribute (LinkedList<TypedAttribute> list, String[] attribute) {
		// for (int i=0; i<attribute[i].length; i++) System.out.println(attribute[i]);
		boolean notNull = false;
		boolean autoIncrement = false;
		if (attribute[4].equals("true")) notNull=true;
		if (attribute[5].equals("true")) autoIncrement=true;
		try {
			if (attribute.length>6) {
				char k = attribute[6].charAt(0);
				list.add( new TypedAttribute(attribute[0],attribute[1],attribute[2],attribute[3],notNull,autoIncrement,k) );
			} else {
				list.add( new TypedAttribute(attribute[0],attribute[1],attribute[2],attribute[3],notNull,autoIncrement) );
			}
		} catch (NoSuchFieldException e) {
			System.err.println("Impossible de créer l'attribut '"+attribute[0]+"'.");
		}
	}


	public static void main(String[] args) {
		if (args.length>0) {
			if (args[0].equalsIgnoreCase("-f"));
			new DbInstaller(true);
			//Trivial pursuit
			new DbTPInstaller(true);
		} else {
			new DbInstaller();
			//Trivial pursuit
			new DbTPInstaller();
		}
	}

}
